/**
 * @Author       : Hejh(3010733382@qq.com)
 * @Version      : V1.0
 * @Date         : 2024-01-22 10:24:42
 * @Description  : 用于用户个人信息更新前的必要检查，与后面的日志记录存在关系
 */
const { Op } = require('sequelize')
const { LOG_TYPE } = require('@/constants/log')
const R = require('@/models/Response')
const { User, Department, UserDepartment, Role } = require('@/models/model')
const { MD5 } = require('@/utils/md5')
const { getUserDepByDepartments } = require('@/utils/getModelInfo')

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 单用户修改时验证参数与数据库发生变化没，如果没有，则无需更新
 * @param {*} ctx
 * @param {*} next
 */
module.exports.singerUpdateCheck = async (ctx, next) => {
  // 进行角色是否需要更新的必要检测
  const { nickname, avator, phone, email, password } = ctx.request.body
  ctx.logs = [
    {
      type: LOG_TYPE.USER_INFO_UPDATE,
      userId: ctx.user.id,
      update: {
        user: {
          id: ctx.user.id
        }
      }
    }
  ]
  let needUpdate = false

  const user = await User.findByPk(BigInt(ctx.user.id), {
    attributes: ['nickname', 'avator', 'phone', 'email', 'password', 'salt']
  })

  const curLog = ctx.logs[0].update

  if (nickname && nickname !== user.nickname) {
    curLog.user.nickname = nickname
    needUpdate = true
  }

  if (avator && avator !== user.avator) {
    curLog.user.avator = avator
    needUpdate = true
  }

  if (phone && phone !== user.phone) {
    curLog.user.phone = phone
    needUpdate = true
  }

  if (email && email !== user.email) {
    curLog.user.email = email
    needUpdate = true
  }

  if (password && user.password !== (await MD5(password, user.salt))) {
    curLog.user.password = '*****'
    needUpdate = true
  }
  if (needUpdate) {
    await next()
  } else {
    ctx.body = R.success()
    return
  }
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 将用户从当前部门中移除前将信息记录下来
 * @param {*} ctx
 * @param {*} next
 */
module.exports.delUserDepsSave = async (ctx, next) => {
  let { userDepIds } = ctx.request.body
  userDepIds = userDepIds.map((v) => BigInt(v))

  const userDeps = await UserDepartment.findAll({
    where: {
      id: {
        [Op.in]: userDepIds
      }
    },
    attributes: ['userId', 'departmentId']
  })

  ctx.logs = []

  // 记录一下用户和部门情况
  for (let i = 0; i < userDeps.length; i++) {
    const user = await User.findByPk(BigInt(userDeps[i].userId), {
      attributes: ['id', 'username']
    })
    const dep = await Department.findByPk(BigInt(userDeps[i].departmentId), {
      attributes: ['id', 'name']
    })
    ctx.logs.push({
      // 外层字段代表现如今操作实体的情况
      userId: ctx.user.id, // 操作者
      type: LOG_TYPE.USER_DEP_REMOVE,
      // 创建时需要记录的东西（是当时的情况）
      delete: {
        user: {
          id: user.id,
          username: user.username
        },
        dep: {
          id: dep.id,
          name: dep.name
        }
      }
    })
  }

  await next()
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 用户删除时的日志记录
 * @param {*} ctx
 * @param {*} next
 */
module.exports.delUserSave = async (ctx, next) => {
  let { userIds } = ctx.request.body
  userIds = userIds.map((v) => BigInt(v))

  const users = await User.findAll({
    where: {
      id: {
        [Op.in]: userIds
      }
    },
    attributes: ['id', 'username']
  })

  ctx.logs = users.map((item) => {
    return {
      type: LOG_TYPE.USER_DEL,
      delete: {
        user: {
          id: item.id,
          username: item.username
        }
      }
    }
  })

  await next()
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 部门单用户修改时验证参数与数据库发生变化没，如果没有，则无需更新
 * @param {*} ctx
 * @param {*} next
 */
module.exports.UserDepSingerUpdateCheck = async (ctx, next) => {
  // 进行角色是否需要更新的必要检测
  const {
    userId,
    username,
    nickname,
    password,
    sizeMax,
    sex,
    email,
    phone,
    roleId,
    departments
  } = ctx.request.body
  ctx.logs = [
    {
      type: LOG_TYPE.USER_UPDATE,
      userId: ctx.user.id,
      update: {
        user: {
          id: userId
        }
      }
    }
  ]
  let needUpdate = false

  const user = await User.findByPk(BigInt(userId), {
    attributes: [
      'username',
      'nickname',
      'avator',
      'phone',
      'email',
      'password',
      'salt',
      'sex',
      'sizeMax',
      'roleId'
    ]
  })

  const curLog = ctx.logs[0].update

  if (username && username !== user.username) {
    curLog.user.username = nickname
    needUpdate = true
  }

  if (sex && sex !== user.sex) {
    curLog.user.sex = sex
    needUpdate = true
  }

  if (sizeMax && sizeMax !== user.sizeMax) {
    curLog.user.sizeMax = sizeMax
    needUpdate = true
  }

  if (roleId && roleId !== user.roleId) {
    // 获取role对应的名称
    const role = await Role.findByPk(BigInt(roleId))
    curLog.user.roleName = role.name
    needUpdate = true
  }

  if (nickname && nickname !== user.nickname) {
    curLog.user.nickname = nickname
    needUpdate = true
  }

  // if (avator && avator !== user.avator) {
  //   curLog.user.avator = avator
  //   needUpdate = true
  // }

  if (phone && phone !== user.phone) {
    curLog.user.phone = phone
    needUpdate = true
  }

  if (email && email !== user.email) {
    curLog.user.email = email
    needUpdate = true
  }

  if (password && user.password !== (await MD5(password, user.salt))) {
    curLog.user.password = '*****'
    needUpdate = true
  }

  // 验证所在部门清空是否发生改变
  const userDeps = await UserDepartment.findAll({
    where: {
      userId
    },
    attributes: ['userId', 'departmentId', 'roleId', 'sizeMax']
  })

  const finalArr = []
  if (userDeps.length !== departments.length) {
    finalArr.push(...departments)
    needUpdate = true
  } else {
    for (let i = 0; i < departments.length; i++) {
      const cur = departments[i]
      // 看是否完全相等
      if (
        userDeps.some(
          (item) =>
            item.departmentId === cur.departmentId &&
            item.roleId === cur.roleId &&
            item.sizeMax === cur.sizeMax
        )
      ) {
      } else {
        needUpdate = true
        finalArr.push(cur)
      }
    }
  }

  const newUserDeps = await getUserDepByDepartments(finalArr)

  curLog.user.userDeps = newUserDeps
  if (needUpdate) {
    await next()
  } else {
    ctx.body = R.success()
    return
  }
}
